home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 4
/
Amiga Tools 4.iso
/
grafix
/
raytracing
/
raylab
/
source
/
algebra.c
next >
Wrap
C/C++ Source or Header
|
1996-01-04
|
4KB
|
236 lines
/*
name: algebra.c
Linear algebra
--------------
These functions simplify vector algebra etc.
*/
#include "defs.h"
void CreateVector(VECTOR *v, double vx, double vy, double vz)
{
v->x=vx;
v->y=vy;
v->z=vz;
}
/* v2 = v1 */
void CopyVector(VECTOR *v2, VECTOR *v1)
{
v2->x=v1->x;
v2->y=v1->y;
v2->z=v1->z;
}
/* v3 = v1 + v2 */
void AddVector(VECTOR *v3, VECTOR *v1, VECTOR *v2)
{
v3->x=(v1->x)+(v2->x);
v3->y=(v1->y)+(v2->y);
v3->z=(v1->z)+(v2->z);
}
/* v3 = v1 - v2 */
void SubVector(VECTOR *v3, VECTOR *v1, VECTOR *v2)
{
v3->x=(v1->x)-(v2->x);
v3->y=(v1->y)-(v2->y);
v3->z=(v1->z)-(v2->z);
}
/* v2 = -v1 */
void NegVector(VECTOR *v2, VECTOR *v1)
{
v2->x=-(v1->x);
v2->y=-(v1->y);
v2->z=-(v1->z);
}
/* v3 = v1 x v2 */
void CrossProduct(VECTOR *v3, VECTOR *v1, VECTOR *v2)
{
v3->x=(v1->y)*(v2->z)-(v1->z)*(v2->y);
v3->y=(v1->z)*(v2->x)-(v1->x)*(v2->z);
v3->z=(v1->x)*(v2->y)-(v1->y)*(v2->x);
}
/* Returns v1 · v2 */
double DotProduct(VECTOR *v1, VECTOR *v2)
{
return((v1->x)*(v2->x)+(v1->y)*(v2->y)+(v1->z)*(v2->z));
}
/* v2 = t * v1 */
void ScaleVector(VECTOR *v2, double t, VECTOR *v1)
{
v2->x=t*(v1->x);
v2->y=t*(v1->y);
v2->z=t*(v1->z);
}
/* Returns |v| */
double VectorLength(VECTOR *v)
{
return(sqrt((v->x)*(v->x)+(v->y)*(v->y)+(v->z)*(v->z)));
}
/* Returns the (smallest) angle between v1 and v2 */
double VectorsAngle(VECTOR *v1, VECTOR *v2)
{
return(acos(DotProduct(v1,v2)/(VectorLength(v1)*VectorLength(v2))));
}
void CreatePoint(POINT *p, double px, double py, double pz)
{
p->x=px;
p->y=py;
p->z=pz;
}
/* p2 = p1 */
void CopyPoint(POINT *p2, POINT *p1)
{
p2->x=p1->x;
p2->y=p1->y;
p2->z=p1->z;
}
/* This routine creates a line from two given points */
void MakeLine(LINE *l, POINT *p1, POINT *p2)
{
CopyPoint(&(l->Origin),p1);
CreateVector(&(l->Direction),(p2->x)-(p1->x),(p2->y)-(p1->y),(p2->z)-(p1->z));
}
/* This routine creates a reflected vector v2, given a vector v1 and a normal n */
void ReflectVector(VECTOR *v2, VECTOR *v1, VECTOR *n)
{
double k,a;
VECTOR vtemp,vtemp2;
CopyVector(&vtemp2,n);
a=PI-VectorsAngle(v1,n);
if((a<0.0)&&(a>-EPSILON)) a+=EPSILON;
if(a>PID2) {
NegVector(&vtemp2,n);
a=PI-a;
}
k=VectorLength(&vtemp2)/(2*cos(a)*VectorLength(v1));
ScaleVector(&vtemp,k,v1);
AddVector(v2,&vtemp,&vtemp2);
/*
if(k<0) NegVector(v2,v2); k<0 <=> from "inside" of object
*/
}
/* This routine rotates a 2D point in a 2D system */
/* I.e. (x,y) rotates (ar) radians counter clockwise around (0,0) */
void Rotate2D(double *x, double *y, double ar)
{
double x1,y1;
x1=(*x)*cos(ar)-(*y)*sin(ar);
y1=(*x)*sin(ar)+(*y)*cos(ar);
*x=x1; *y=y1;
}
/* This routine rotates a 3D point in 3D space. The point (x,y,z) */
/* is rotated around the x, the y and the z axis (in that order). */
/* The vector RotV gives the degrees to rotate around each axis */
void RotatePoint(POINT *p, VECTOR *RotV)
{
double x1,y1,z1;
x1=p->x; y1=p->y; z1=p->z;
if(RotV->x!=0.0) Rotate2D(&y1,&z1,RotV->x);
if(RotV->y!=0.0) Rotate2D(&z1,&x1,RotV->y);
if(RotV->z!=0.0) Rotate2D(&x1,&y1,RotV->z);
p->x=x1; p->y=y1; p->z=z1;
}
/* This is the same thing, but with a vector instead of a point. */
void RotateVector(VECTOR *v, VECTOR *RotV)
{
double x1,y1,z1;
x1=v->x; y1=v->y; z1=v->z;
if(RotV->x!=0.0) Rotate2D(&y1,&z1,RotV->x);
if(RotV->y!=0.0) Rotate2D(&z1,&x1,RotV->y);
if(RotV->z!=0.0) Rotate2D(&x1,&y1,RotV->z);
v->x=x1; v->y=y1; v->z=z1;
}
/* These routines will rotate in the reversed order (z,y,x). */
void RevRotatePoint(POINT *p, VECTOR *RotV)
{
double x1,y1,z1;
x1=p->x; y1=p->y; z1=p->z;
if(RotV->z!=0.0) Rotate2D(&x1,&y1,RotV->z);
if(RotV->y!=0.0) Rotate2D(&z1,&x1,RotV->y);
if(RotV->x!=0.0) Rotate2D(&y1,&z1,RotV->x);
p->x=x1; p->y=y1; p->z=z1;
}
void RevRotateVector(VECTOR *v, VECTOR *RotV)
{
double x1,y1,z1;
x1=v->x; y1=v->y; z1=v->z;
if(RotV->z!=0.0) Rotate2D(&x1,&y1,RotV->z);
if(RotV->y!=0.0) Rotate2D(&z1,&x1,RotV->y);
if(RotV->x!=0.0) Rotate2D(&y1,&z1,RotV->x);
v->x=x1; v->y=y1; v->z=z1;
}